﻿using BLevy.Datos.Interfases;
using BLevy.Entidad;
using MySql.Data.MySqlClient;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Dapper;
using DapperExtensions;

namespace BLevy.Datos.Repositories
{
    public interface IPlanRepository : IRepository<Plan>
    {
        int AddPlan(Plan plan);
        IList<AdicionalPlan> FindAdicionalesByPlan(int plan_id);
        IList<AdicionalPlan> FindAllAdicionales();
        int Modify(Plan entity, IList<int> adicionalesEliminar);
    }

    public class PlanRepository:IPlanRepository
    {
        protected readonly IDbConnection _db;

        public PlanRepository()
        {
            try
            {
                _db = new MySqlConnection(ConfigurationManager.ConnectionStrings["LEVYDB"].ToString());
            }
            catch(Exception e)
            {
                throw e;
            }
        }

        public IList<Plan> FindAll()
        {
            try
            {
                using (IDbConnection _db = new MySqlConnection(ConfigurationManager.ConnectionStrings["LEVYDB"].ToString()))
                {
                    return _db.Query<Plan>("SELECT * FROM PLANES ORDER BY ID ASC").ToList();
                }
            }
            catch(Exception e)
            {
                throw e;
            }
        }

        public IQueryable<Plan> Find(System.Linq.Expressions.Expression<Func<Plan, bool>> predicate)
        {
            throw new NotImplementedException();
        }

        public Plan FindById(int id)
        {
            string query = "SELECT * FROM PLANES " +
                "WHERE ID = @id";

            try
            {
                using (IDbConnection _db = new MySqlConnection(ConfigurationManager.ConnectionStrings["LEVYDB"].ToString()))
                {
                    return _db.Query<Plan>(query, new { id = id }).SingleOrDefault();
                }
            }
            catch(Exception e)
            {
                throw e;
            }
        }

        public int Remove(int id)
        {
            string query = "UPDATE PLANES SET ACTIVO = 0 " +
                "WHERE ID = @id";

            try
            {
                using (IDbConnection _db = new MySqlConnection(ConfigurationManager.ConnectionStrings["LEVYDB"].ToString()))
                {
                    return _db.Execute(query, new { id = id });
                }
            }
            catch(Exception e)
            {
                throw e;
            }
        }

        public int AddPlan(Plan plan)
        {
            int resultado = 0;

            string query = "INSERT INTO PLANES (NOMBRE, DESCRIPCION, FECHAREGISTRO, COSTO_BASE, TITULAR, EDAD_TITULAR, CONYUGE, EDAD_CONYUGE, HIJOS, CANTIDAD_HIJOS, EDAD_HIJOS, OTROS, CANTIDAD_OTROS, EDAD_OTROS, ACTIVO, RECARGO) " +
                "VALUES (@nombre, @descripcion, @fecharegistro, @costo_base, @titular, @edad_titular, @conyuge, @edad_conyuge, @hijos, @cantidad_hijos, @edad_hijos, @otros, @cantidad_otros, @edad_otros, @activo, @recargo);";

            try
            {
                using (IDbConnection _db = new MySqlConnection(ConfigurationManager.ConnectionStrings["LEVYDB"].ToString()))
                {
                    _db.Open();
                    using (var tran = _db.BeginTransaction())
                    {
                        try
                        {
                            int planes = _db.Execute(query, new
                            {
                                nombre = plan.nombre,
                                descripcion = plan.descripcion,
                                fecharegistro = DateTime.Now,
                                costo_base = plan.costo_base,
                                titular = plan.titular,
                                edad_titular = plan.edad_titular,
                                conyuge = plan.conyuge,
                                edad_conyuge = plan.edad_conyuge,
                                hijos = plan.hijos,
                                cantidad_hijos = plan.cantidad_hijos,
                                edad_hijos = plan.edad_hijos,
                                otros = plan.otros,
                                cantidad_otros = plan.cantidad_otros,
                                edad_otros = plan.edad_otros,
                                activo = plan.activo,
                                recargo = plan.recargo
                            });

                            if (planes > 0)
                            {
                                bool res = true;

                                Plan plan_id = _db.Query<Plan>("SELECT * FROM PLANES ORDER BY ID DESC").FirstOrDefault();

                                string queryAdicionales = "INSERT INTO ADICIONALESPLANES (PLAN_ID, EDAD_DESDE, EDAD_HASTA, COSTO_ADICIONAL) " +
                                    "VALUES (@plan_id, @edad_desde, @edad_hasta, @costo_adicional);";

                                if (plan.adicionales.Count > 0)
                                {
                                    foreach (var a in plan.adicionales)
                                    {
                                        resultado = _db.Execute(queryAdicionales, new
                                        {
                                            plan_id = plan_id.id,
                                            edad_desde = a.edad_desde,
                                            edad_hasta = a.edad_hasta,
                                            costo_adicional = a.costo_adicional
                                        });

                                        if (resultado == 0)
                                        {
                                            res = false;
                                            break;
                                        }
                                    }
                                }

                                if (res == true)
                                {
                                    tran.Commit();
                                }
                                else
                                {
                                    tran.Rollback();
                                    resultado = 0;
                                }
                            }

                            return resultado;
                        }
                        catch
                        {
                            tran.Rollback();
                            resultado = 0;

                            return resultado;
                        }
                    }

                }
            }
            catch (Exception e)
            {
                throw e;
            }
        }

        public IList<AdicionalPlan> FindAdicionalesByPlan(int plan_id)
        {
            string query = "SELECT * FROM ADICIONALESPLANES " +
                "WHERE PLAN_ID = @plan " +
                "ORDER BY EDAD_DESDE, EDAD_HASTA";

            try
            {
                using (IDbConnection _db = new MySqlConnection(ConfigurationManager.ConnectionStrings["LEVYDB"].ToString()))
                {
                    return _db.Query<AdicionalPlan>(query, new { plan = plan_id }).ToList();
                }
            }
            catch (Exception e)
            {
                throw e;
            }
        }


        public int Add(Plan newEntity)
        {
            throw new NotImplementedException();
        }

        public int Modify(Plan entity, IList<int> adicionalesEliminar)
        {
            int resultado_plan;
            int resultado_adherente = 0;
            int resultado_adherente_nuevo = 0;
            int resultado_adicional_eliminado = 0;


            string query = "UPDATE PLANES SET nombre = @nombre, descripcion = @descripcion, fecharegistro = @fecharegistro, costo_base = @costo_base, titular = @titular, edad_titular = @edad_titular, " +
                            "conyuge = @conyuge, edad_conyuge = @edad_conyuge, hijos = @hijos, cantidad_hijos = @cantidad_hijos, edad_hijos = @edad_hijos, otros = @otros, cantidad_otros = @cantidad_otros, " +
                            "edad_otros = @edad_otros, activo = @activo, recargo = @recargo " +
                            "WHERE id = @id";

            string query_adicionales = "UPDATE ADICIONALESPLANES SET PLAN_ID = @plan_id, EDAD_DESDE = @edad_desde, EDAD_HASTA = @edad_hasta, COSTO_ADICIONAL = @costo_adicional " +
                                        "WHERE ID = @id";

            string query_insert_adicionales = "INSERT INTO ADICIONALESPLANES (PLAN_ID, EDAD_DESDE, EDAD_HASTA, COSTO_ADICIONAL) VALUES (@plan_id, @edad_desde, @edad_hasta, @costo_adicional)";

            string query_eliminar_adicionales = "DELETE FROM adicionalesplanes WHERE ID = @id";

            using (IDbConnection _db = new MySqlConnection(ConfigurationManager.ConnectionStrings["LEVYDB"].ToString()))
            {
                _db.Open();
                IDbTransaction transaction = _db.BeginTransaction();

                try
                {
                    resultado_plan = _db.Execute(query, new
                    {
                        id = entity.id,
                        nombre = entity.nombre,
                        descripcion = entity.descripcion,
                        fecharegistro = entity.fecharegistro,
                        costo_base = entity.costo_base,
                        titular = entity.titular,
                        edad_titular = entity.edad_titular,
                        conyuge = entity.conyuge,
                        edad_conyuge = entity.edad_conyuge,
                        hijos = entity.hijos,
                        cantidad_hijos = entity.cantidad_hijos,
                        edad_hijos = entity.edad_hijos,
                        otros = entity.otros,
                        cantidad_otros = entity.cantidad_otros,
                        edad_otros = entity.edad_otros,
                        activo = entity.activo,
                        recargo = entity.recargo

                    }, transaction);

                    if (resultado_plan > 0)
                    {
                        foreach (AdicionalPlan adicional in entity.adicionales)
                        {
                            //esta registrado
                            if (adicional.id != 0)
                            {
                                resultado_adherente = _db.Execute(query_adicionales, new
                                {
                                    id = adicional.id,
                                    plan_id = entity.id,
                                    edad_desde = adicional.edad_desde,
                                    edad_hasta = adicional.edad_hasta,
                                    costo_adicional = adicional.costo_adicional
                                }, transaction);

                                if (!(resultado_adherente > 0))
                                {
                                    transaction.Rollback();
                                    return resultado_adherente;
                                }
                            }
                            else //no esta registrado - inserto uno nuevo
                            {
                                resultado_adherente_nuevo = _db.Execute(query_insert_adicionales, new
                                {
                                    plan_id = entity.id,
                                    edad_desde = adicional.edad_desde,
                                    edad_hasta = adicional.edad_hasta,
                                    costo_adicional = adicional.costo_adicional
                                }, transaction);

                                if (!(resultado_adherente_nuevo > 0))
                                {
                                    transaction.Rollback();
                                    return resultado_adherente;
                                }
                            }
                        }

                        if (adicionalesEliminar.Count > 0)
                        {
                            foreach(int adicionalEliminar in adicionalesEliminar)
                            {
                                resultado_adicional_eliminado = _db.Execute(query_eliminar_adicionales, new { id = adicionalEliminar },transaction);
                                if (!(resultado_adicional_eliminado > 0))
	                            {
		                             transaction.Rollback();
                                    return resultado_adicional_eliminado;
                                }
                            }
                        }

                        transaction.Commit();
                    }
                    else
                    {
                        transaction.Rollback();
                    }
                }
                catch (Exception e)
                {
                    transaction.Rollback();
                    throw e;
                }
            }
            
            return resultado_plan;
        }


        public IList<AdicionalPlan> FindAllAdicionales()
        {
            const string query = "SELECT * FROM ADICIONALESPLANES";
            
            try
            {
                using (IDbConnection _db = new MySqlConnection(ConfigurationManager.ConnectionStrings["LEVYDB"].ToString()))
                {
                    return _db.Query<AdicionalPlan>(query).ToList();
                }
            }
            catch (Exception e)
            {
                throw e;
            }
        }

        int IRepository<Plan>.Modify(Plan entity)
        {
            throw new NotImplementedException();
        }
    }
}
